<?php

/**
 * Hoa Framework
 *
 *
 * @license
 *
 * GNU General Public License
 *
 * This file is part of Hoa Open Accessibility.
 * Copyright (c) 2007, 2008 Ivan ENDERLIN. All rights reserved.
 *
 * HOA Open Accessibility is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * HOA Open Accessibility is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with HOA Open Accessibility; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *
 * @category    Framework
 * @package     Hoa_Console
 * @subpackage  Hoa_Console_Interface_Animation
 *
 */

/**
 * Hoa_Framework
 */
require_once 'Framework.php';

/**
 * Hoa_Console_Interface_Exception
 */
import('Console.Interface.Exception');

/**
 * Hoa_Console_Core_Io
 */
import('Console.Core.Io');

/**
 * Class Hoa_Console_Interface_Animation.
 *
 * This class allows to make an animation on a single line (by using the \r
 * special char, not with cleaning screen for each animation frame).
 * See the self::render() method to know tips.
 *
 * @author      Ivan ENDERLIN <ivan.enderlin@hoa-project.net>
 * @copyright   Copyright (c) 2007, 2008 Ivan ENDERLIN.
 * @license     http://gnu.org/licenses/gpl.txt GNU GPL
 * @since       PHP 5
 * @version     0.1
 * @package     Hoa_Console
 * @subpackage  Hoa_Console_Interface_Animation
 */

abstract class Hoa_Console_Interface_Animation {

    /**
     * The animation parameters. Should be overload by childs.
     *
     * @var Hoa_Console_Interface_Animation
     */
    protected $parameters = array();



    /**
     * Built an animation and set parameters.
     *
     * @access  public
     * @param   array   $parameters    Animation parameters.
     * @return  void
     * @throw   Hoa_Console_Interface_Exception
     */
    public function __construct ( Array $parameters = array() ) {

        $this->setParameters($parameters);
    }

    /**
     * Set a group of parameters.
     *
     * @access  public
     * @param   array   $parameters    Animation parameters.
     * @return  void
     * @throw   Hoa_Console_Interface_Exception
     */
    public function setParameters ( Array $parameters ) {

        foreach($parameters as $parameter => $value)
            $this->setParameter($parameter, $value);
    }

    /**
     * Set a specific parameter.
     *
     * @access  public
     * @param   string  $parameter    The parameter name.
     * @param   mixed   $value        The parameter value.
     * @return  mixed
     * @throw   Hoa_Console_Interface_Exception
     */
    public function setParameter ( $parameter, $value ) {

        if(false === $this->parameterExists($parameter))
            throw new Hoa_Console_Interface_Exception(
                'The %s parameter does not exist.', 0, $parameter);

        $old                          = $this->parameters[$parameter];
        $this->parameters[$parameter] = $value;

        return $old;
    }

    /**
     * Get a specific parameter value.
     *
     * @access  public
     * @param   string  $parameter    The parameter name.
     * @return  mixed
     * @throw   Hoa_Console_Interface_Exception
     */
    public function getParameter ( $parameter ) {

        if(false === $this->parameterExists($parameter))
            throw new Hoa_Console_Interface_Exception(
                'The %s parameter does not exist.', 1, $parameter);

        return $this->parameters[$parameter];
    }

    /**
     * Check if a parameter already exist.
     *
     * @access  public
     * @param   string  $parameter    The parameter name.
     * @return  bool
     */
    public function parameterExists ( $parameter ) {

        return    isset($this->parameters[$parameter])
               && null !== $this->parameters[$parameter];
    }

    /**
     * Make a render of an animation.
     * The animation is cut in different frames. Each frame is generated by
     * calling the self::animationFrame() method that returns the current frame
     * number. This number is given to the self::animationRender() method that
     * returns the painted frame.
     * The animation frame number is given by calling the
     * self::animationFrameMax() method.
     *
     * @access  public
     * @return  int
     */
    final public function render ( ) {

        $i   = 0;
        $max = $this->animationFrameMax();

        while($i < $max) {

            $i      = $this->animationFrame($i);
            $render = $this->animationRender($i, $max);

            Hoa_Console_Core_Io::cout(
                "\r" . $render,
                Hoa_Console_Core_Io::NO_NEW_LINE
            );
        }

        return $i;
    }

    /**
     * A render calls the self::animationFrameMax() method to get the max number
     * of frame that the animation has.
     *
     * @acccess  protected
     * @return   int
     */
    abstract protected function animationFrameMax ( );

    /**
     * A render calls the self::animationFrame() method to get the current
     * frame number.
     *
     * @access  protected
     * @param   int        $i    The previous frame number.
     * @return  int
     */
    abstract protected function animationFrame ( $i );

    /**
     * And finally, a render calls the self::animationRender() method to get
     * the string/render of the current frame (given by $i).
     *
     * @access  protected
     * @param   int        $i      The current frame number.
     * @param   int        $max    Max number of frame.
     * @return  string
     * @throw   Hoa_Console_Interface_Exception
     */
    abstract protected function animationRender ( $i, $max );
}
